#include "compiler.h"
#include "parser.h"
#include "core.h"
#include "common.h"

#ifdef DEBUG
    #include "debug.h"
#endif

#define OPCODE_SLOTS(opcode, effect) effect,
static const int opcode_slot_used[] = 
{
    #include "opcode.inc"
};
#undef OPCODE_SLOTS

struct compileUnit
{
    ObjFn *fn; 
    LocalVar local_vars[MAX_LOCAL_VAR_NUM];
    uint32_t local_var_num; 
    Upvalue upvalues[MAX_UPVALUE_NUM]; // 记录本层函数所引用的upvalue
    int scope_depth;
    uint32_t stack_slots_num; // 当前使用的slot个数
    Loop **cur_loop;
    ClassBookKeep *enclosing_class_bk;
    struct compileUnit *enclosing_unit; // 直接外层编译单元
    Parser *cur_parser;
};

typedef enum 
{
    BP_NONE, 
    // 从上往下，优先级越来越高
    BP_LOWEST,
    BP_ASSIGN, // =
    BP_CONDITION, // ? :
    BP_LOGIC_OR,
    BP_LOGIC_AND,
    BP_EQUAL, // == !=
    BP_IS,
    BP_CMP, // < > <= >=
    BP_BIT_OR,
    BP_BIT_AND,
    BP_RANGE, // ..
    BP_TERM, // + -
    BP_FACTOR, // * / %
    BP_UNARY, // - ! ~
    BP_CALL, // . () []
    BP_HIGHEST
} BindPower;

// 指示符函数指针
typedef void (*denotation_fn)(CompileUnit *cu, bool can_assign);

// 签名函数指针
typedef void (*method_signature_fn)(CompileUnit *cu, Signature *signature);

typedef struct 
{
    const char *id; // 符号

    BindPower lbp; // 左绑定权值

    denotation_fn nud;// 字面量 变量 前缀运算符等不关注左操作数的Token调用方法

    denotation_fn led; // 中缀运算符等关注左操作数的Token调用的方法

    method_signature_fn method_sign; // 表示本符号在类中被视为一个方法，为其生产一个方法签名
} SymbolBindRule; // 符号绑定规则

typedef enum 
{
    VAR_SCOPE_INVALID, VAR_SCOPE_LOCAL, VAR_SCOPE_UPVALUE, VAR_SCOPE_MODULE
} VarScopeType;  // 标识变量作用域

typedef struct 
{
    VarScopeType scope_type;
    int index; // 根据scope_type的值，此索引可能指向局部变量或者upvalue或模块变量
} Variable;

/**
 * @brief 在模块objModule中定义名为name，值为value的模块变量
*/
int define_module_var(VM *vm, ObjModule *obj_module, const char *name, uint32_t length, Value value)
{
    if (length > MAX_ID_LEN)
    {
        char id[MAX_ID_LEN] = { '\0' };
        memcpy(id, name, length);

        /**
         * 本函数可能是在编译源码文件之前调用的，那时还没有创建parser
        */
        if (vm->cur_parser != NULL)
        {
            COMPILE_ERROR(vm->cur_parser, "length of identifier \"%s\" should be no more than %d", id, MAX_ID_LEN);
        }
        else
        { // 编译源码前调用，比如加载核心模块时会调用此函数
            MEM_ERROR("length of identifier \"%s\" should be no more than %d", id, MAX_ID_LEN);
        }
    }

    int symbol_index= get_index_from_symbol_table(&obj_module->module_var_name, name, length);
    if (symbol_index == -1)
    {
        symbol_index = add_symbol(vm, &obj_module->module_var_name, name, length);

        Value_buffer_add(vm, &obj_module->module_var_value, value);
    }
    else if (VALUE_IS_NUM(obj_module->module_var_value.datas[symbol_index]))
    {
        obj_module->module_var_value.datas[symbol_index] = value;
    }
    else
    {
        symbol_index = -1;
    }

    return symbol_index;
}

/**
 * @brief 编译模块 
 * 脚本文件被认为是一个模块，加载模块是从编译到执行的国产，目前先完成模块加载的准备工作
*/
ObjFn* compile_module(VM *vm, ObjModule *obj_module, const char *module_core)
{
    // 各源码模块文件需要单独的parser
    Parser parser;
    parser.parent = vm->cur_parser;
    vm->cur_parser = &parser;

    if (obj_module->name == NULL) // 核心模块的name是NULL
    {
        // 核心模块是core.script.inc
        init_parser(vm, &parser, "core.script.inc", module_core, obj_module);
    }
    else
    {
        init_parser(vm, &parser,  (const char *)obj_module->name->value.start, module_core, obj_module);
    }

    CompileUnit module_cu;
    init_compileUnit(&parser, &module_cu, NULL, false);

    // 记录现在模块变量的数量，后面检查预定义模块变量时可减少遍历
    uint32_t module_var_num_befor = obj_module->module_var_value.count;

    // 初始的parser->cur_token.type为TOKEN_UNKNOWN,下面使其指向第一个合法的token
    get_next_token(&parser);

    while (!match_token(&parser, TOKEN_EOF))
    {
        compile_program(&module_cu);
    }

    printf("There is something to do...\n");
    exit(0);
}

/**
 * @brief 编译程序
*/
static void compile_program(CompileUnit *cu)
{

}

/**
 * @brief 初始化compileunit
*/
static void init_compileUnit(Parser *parser, CompileUnit *cu, CompileUnit *enclosing_unit, bool is_method)
{
    parser->cur_compileUnit = cu;
    cu->cur_parser = parser;
    cu->enclosing_unit = enclosing_unit;
    cu->cur_loop = NULL;
    cu->enclosing_class_bk = NULL;

    /**
     * 如果没有外层直接编译单元，说明当前属于模块作用域
    */
    if (enclosing_unit == NULL)
    {
        // 编译代码时是从上到下最外层的模块作用域开始，模块作用域为-1
        cu->scope_depth = -1;
        // 模块级作用域中没有局部变量
        cu->local_var_num = 0;
    }
    else
    {
        if (is_method) // 如果是类中的方法
        {
            cu->local_vars[0].name = "this";
            cu->local_vars[0].length = 4;
        }
        else // 如果是普通函数
        {
            // 空出第0个局部变量，保持统一
            cu->local_vars[0].name = NULL;
            cu->local_vars[0].length = 0;
        }
        cu->local_vars[0].scope_depth = -1;
        cu->local_vars[0].is_upvalue = false;
        cu->local_var_num = 1;
        cu->scope_depth = 0; // TODO
    }
    // 局部变量保存在栈中，初始时栈中已使用的slot数量等于局部变量的数量
    cu->stack_slots_num = cu->local_var_num;

    cu->fn = new_objFn(cu->cur_parser->vm, cu->cur_parser->cur_module, cu->local_var_num);
}

/**
 * @brief 在函数的指令流中写入1字节，返回其索引
*/
static int write_byte(CompileUnit *cu, int byte)
{
#ifdef DEBUG
    Int_buffer_add(cu->cur_parser->vm, &cu->fn->debug->lineNo, cu->cur_parser->pre_token.lineNo);
#endif
    Byte_buffer_add(cu->cur_parser->vm, &cu->fn->instruct_stream, (uint8_t) byte);
    return cu->fn->instruct_stream.count - 1;
}

/**
 * @brief 写入操作码
*/
static void write_opcode(CompileUnit *cu, OpCode opcode)
{
    write_byte(cu, opcode);

    cu->stack_slots_num += opcode_slot_used[opcode];
    if (cu->stack_slots_num > cu->fn->max_stack_slot_used_num)
    {
        cu->fn->max_stack_slot_used_num = cu->stack_slots_num; // 记录栈使用的峰值
    }
}

/**
 * @brief 写入1字节的操作数
*/
static int write_byte_operand(CompileUnit *cu, int operand)
{
    return write_byte(cu, operand);
}

/**
 * @brief 写入2个字节的操作数，按大端字节序写入参数
*/
inline static void write_short_operand(CompileUnit *cu, int operand)
{
    write_byte(cu, (operand >> 8) & 0xff);
    write_byte(cu, operand & 0xff);
}

/**
 * @brief 写入操作数为1字节大小的指令
*/
static int write_opcode_byte_operand(CompileUnit *cu, OpCode opcode, int operand)
{
    write_opcode(cu, opcode);
    return write_byte_operand(cu, operand);
}

/**
 * @brief 写入操作数为2字节大小的指令
*/
static void write_opcode_short_operand(CompileUnit *cu, OpCode opcode, int operand)
{
    write_opcode(cu, opcode);
    write_short_operand(cu, operand);
}

/**
 * @brief 添加常量并返回其索引
*/
static uint32_t add_constant(CompileUnit *cu, Value constant)
{
    Value_buffer_add(cu->cur_parser->vm, &cu->fn->constants, constant);
    return cu->fn->constants.count - 1;
}

/**
 * @brief 生成加载常量的指令
*/
static void emit_load_constant(CompileUnit *cu, Value value)
{
    int index = add_constant(cu, value);
    write_opcode_short_operand(cu, OPCODE_LOAD_CONSTANT, index);
}

/**
 * @brief 数字和字符串.nud() 编译字面量
*/
static void literal(CompileUnit *cu, bool can_assign UNUSED)
{
    emit_load_constant(cu, cu->cur_parser->pre_token.value);
}

/**
 * id bp(lbp)  
*/
// 不关注左操作数的符号成为前缀符号
// 用于如字面量 变量名 前缀符号等非运算符
#define PREFIX_SYMBOL(nud) { NULL, BP_NONE, nud, NULL, NULL }
// 前缀运算符 如！
#define PREFIX_OPERATOR(id) { id, BO_NONE, unaryOperator, NULL, unary_method_signature }
// 关注左操作数的符号成为中缀符号
// 数组[ 函数（，实例与方法之间的.等
#define INFIX_SYMBOL(lbp, led) { NULL, lbp, NULL, led, NULL }
// 中缀运算符
#define INFIX_OPERATOR(id, lbp) { id, lbp, NULL, infix_operator, infix_method_signature }
// 既可左前缀也可以左中缀的运算符 如-
#define MIX_OPERATOR(id) { id , BP_TERM, unary_operator, infix_operator, mix_method_signature }
// 占位用的
#define UNUSED_RULE { NULL, BP_NONE, NULL, NULL, NULL }

/**
 * @brief 将Signature转换为字符串，返回字符串长度
*/
static uint32_t sign_to_string(Signature *sign, char *buf)
{
    uint32_t pos = 0;
    memcpy(buf + pos, sign->name, sign->length);
    pos += sign->length;

    switch (sign->type)
    {
        case SIGN_GETTER:
            break;
        case SIGN_SETTER:
        {
            buf[pos ++] = '=';
            buf[pos ++] = '_';
            buf[pos ++] = ')';
            break;
        }
        case SIGN_CONSTRUCT:
        {
            buf[pos ++] = '(';
            uint32_t idx = 0;
            while (idx < sign->arg_num)
            {
                buf[pos ++] = '_';
                buf[pos ++] = ',';
                idx ++;
            }
            if (idx == 0)  // 说明没有参数
            {
                buf[pos ++] = ')';
            }
            else
            {
                buf[pos - 1] = ')';
            }
            break;
        }
        case SIGN_SUBSCRIPT:
        {
            buf[pos ++] = '[';
            uint32_t idx = 0;
            while (idx < sign->arg_num)
            {
                buf[pos ++] = '_';
                buf[pos ++] = ',';
                idx ++;
            }
            if (idx == 0)  // 说明没有参数
            {
                buf[pos ++] = ']';
            }
            else
            {
                buf[pos - 1] = ']';
            }
            break;
        }
        case SIGN_SUBSCRIPT_SETTER:
        {
            buf[pos ++] = '[';
            uint32_t idx = 0;
            while (idx < sign->arg_num)
            {
                buf[pos ++] = '_';
                buf[pos ++] = ',';
                idx ++;
            }
            if (idx == 0)  // 说明没有参数
            {
                buf[pos ++] = ']';
            }
            else
            {
                buf[pos - 1] = ']';
            }
            buf[pos ++] = '=';
            buf[pos ++] = '(';
            buf[pos ++] = '_';
            buf[pos ++] = ')';
            break;
        }
    }
    buf[pos] = '\0';
    return pos;
}

/**
 * @brief 语法分析的核心 expression只负责计算表达式的结果 包括数字表达式与其他操作符组成的表达式 OP
 * @param cu 编译单元
 * @param rbp 算符
 * @category TDOP
*/
static void expression(CompileUnit *cu, BindPower rbp)
{
    /**
     * Rules数组对每个token的expression是按照token列表来排列的
     * 根据token获取对应的SymbolBindRule
    */
    denotation_fn nud = Rules[cu->cur_parser->cur_token.type].nud;

    ASSERT(nud != NULL, "nud is NULL!");

    get_next_token(cu->cur_parser); 

    bool can_assign = rbp < BP_ASSIGN;
 
    nud(cu, can_assign);

    while (rbp < Rules[cu->cur_parser->cur_token.type].lbp)
    {
        denotation_fn led = Rules[cu->cur_parser->cur_token.type].led;
        get_next_token(cu->cur_parser); 
        led(cu, can_assign);
    }
}

/**
 * @brief 通过签名编译方法调用
*/
static void emit_call_by_signature(CompileUnit *cu, Signature *sign, OpCode opcode)
{
    char signBuffer[MAX_SIGN_LEN];
    uint32_t length = sign_to_string(sign, signBuffer);

    int symbol_index = ensure_symbol_exist(cu->cur_parser->vm, &cu->cur_parser->vm->all_method_names, signBuffer, length);

    write_opcode_short_operand(cu, opcode + sign->arg_num, symbol_index);

    // 此时在常量表中预创建一个空slot位，将来绑定方法时再装入基类
    if (opcode == OPCODE_SUPER0)
    {
        write_short_operand(cu, add_constant(cu, VT_TO_VALUE(VT_NULL)));
    }
}

/**
 * @brief 生成方法调用的指令，仅限callX指令
*/
static void emit_call(CompileUnit *cu, int num_args, const char *name, int length)
{
    int symbol_index = ensure_symbol_exist(cu->cur_parser->vm, &cu->cur_parser->vm->all_method_names, name, length);
    write_opcode_short_operand(cu, OPCODE_CALL0 + num_args, symbol_index);
}

/**
 * @brief 中缀运算符 .led方法
*/
static void infix_operator(CompileUnit *cu, bool can_assign UNUSED)
{
    SymbolBindRule *rule = &Rules[cu->cur_parser->pre_token.type];

    // 中缀运算符对左右操作数的绑定权值一样
    BindPower rbp = rule->lbp;
    expression(cu, rbp); // 解析右操作数

    Signature sign = { SIGN_METHOD, rule->id, strlen(rule->id), 1 };
    emit_call_by_signature(cu, &sign, OPCODE_CALL0);

}

/**
 * @brief 前缀运算符  .nud方法 不关注左操作数
 * 进入任何一个符号的led或nud方法时，pre_token都是该方法所属于的符号（操作符）,cur_token是操作数
*/
static void unary_operator(CompileUnit *cu, bool can_assign UNUSED)
{
    SymbolBindRule *rule = &Rules[cu->cur_parser->pre_token.type];

    // BP_UNARY作为rbp去调用expression解析右边操作数
    expression(cu, BP_UNARY);

    // 生成调用前缀运算符的指令
    // 0个参数，前缀运算符都是1个字符，长度是1
    emit_call(cu, 0, rule->id, 1);
}

/**
 * @brief 添加局部变量到cu
*/
static uint32_t add_local_var(CompileUnit *cu, const char *name, uint32_t length)
{
    LocalVar *var = &(cu->local_vars[cu->local_var_num]);
    var->name = name;
    var->length = length;
    var->scope_depth = cu->scope_depth;
    var->is_upvalue = false;
    return cu->local_var_num ++;
}

/**
 * @brief 声明局部变量
*/
static int declare_local_var(CompileUnit *cu, const char *name, uint32_t length)
{
    if (cu->local_var_num >= MAX_LOCAL_VAR_NUM) // 达到局部变量存储上限
    {
        COMPILE_ERROR(cu->cur_parser, "the max length of local variable of one scope is %d", MAX_LOCAL_VAR_NUM);
    }
    int idx = (int)cu->local_var_num - 1;
    while (idx >= 0)
    {
        LocalVar *var = &cu->local_vars[idx];

        // 如果到了父作用域就退出
        if (var->scope_depth < cu->scope_depth)
        {
            break;
        }

        if (var->length == length && memcmp(var->name, name, length) == 0)
        {
            char id[MAX_ID_LEN] = { '\0' };
            memcpy(id, name, length);
            COMPILE_ERROR(cu->cur_parser, "identifier \"%s\" redefinition!", id);
        }

        idx --;
    }
    // 检查过后声明该局部变量
    return add_local_var(cu, name, length);
}

/**
 * @brief 根据作用域声明变量
*/
static int declare_variable(CompileUnit *cu, const char *name, uint32_t length)
{
    // 若当前是模块作用域就声明为模块变量
    if (cu->scope_depth == -1)
    {
        int index = define_module_var(cu->cur_parser->vm, cu->cur_parser->cur_module, name, length, VT_TO_VALUE(VT_NULL));

        if (index == -1)  // 重定义
        {
            char id[MAX_ID_LEN] = { '\0' };
            memcpy(id, name, length);
            COMPILE_ERROR(cu->cur_parser, "identifier \"%s\" redefinition!", id);  
        }
    }

    // 否则是局部作用域
    return declare_local_var(cu, name, length);
}

/**
 * @brief 为单运算符方法创建签名
*/
static void unary_method_signature(CompileUnit *cu UNUSED, Signature *sign UNUSED)
{
    // 名称在调用前一句完成，只修改类型
    sign->type = SIGN_GETTER;
}

/**
 * @brief 为中缀运算符创建签名
*/
static void infix_method_signature(CompileUnit *cu, Signature *sign)
{
    sign->type = SIGN_METHOD; // 在类中的运算符都是方法，类型是SIGN_METHOD

    sign->arg_num = 1;  // 中缀运算符只有一个参数，故初始为1
    consume_cur_token(cu->cur_parser, TOKEN_LEFT_PAREN, "expect '(' after infix operator!");
    consume_cur_token(cu->cur_parser, TOKEN_ID, "expect variable name!");
    declare_variable(cu, cu->cur_parser->pre_token.start, cu->cur_parser->pre_token.length);
    consume_cur_token(cu->cur_parser, TOKEN_RIGHT_PAREN, "expect '(' after infix parameter!");
}

/**
 * @brief 为既做单运算符又做中缀运算符的符号方法创建签名
*/
static void mix_method_signature(CompileUnit *cu, Signature *sign)
{
    // 假设是单运算符方法，因此默认为getter
    sign->type = SIGN_GETTER;

    // 若后面有（，说明其为中缀运算符，则为SIGN_METHOD
    if (match_token(cu->cur_parser, TOKEN_LEFT_PAREN))
    {
        sign->type = SIGN_METHOD;
        sign->arg_num = 1;
        consume_cur_token(cu->cur_parser, TOKEN_ID, "expect variable name!");
        declare_variable(cu, cu->cur_parser->pre_token.start, cu->cur_parser->pre_token.length);
        consume_cur_token(cu->cur_parser, TOKEN_RIGHT_PAREN, "expect '(' after infix parameter!");
    }
}

/**
 * @brief 声明模块变量 只做声明 不做重定义检查
*/
static int declare_module_var(VM *vm, ObjModule *obj_module, const char *name, uint32_t length, Value value)
{
    Value_buffer_add(vm, &obj_module->module_var_value, value);
    return add_symbol(vm, &obj_module->module_var_name, name, length);
}

/**
 * @brief 返回包含cu->enclosing最近的编译单元
*/
static CompileUnit* get_enclosing_classbkunit(CompileUnit *cu)
{
    while (cu != NULL)
    {
        if (cu->enclosing_class_bk != NULL)
        {
            return cu;
        }
        cu = cu->enclosing_unit;
    }
    return NULL;
}

/**
 * @brief 返回包含cu最近的classbk
*/
static ClassBookKeep* get_enclosing_classbk(CompileUnit *cu)
{
    CompileUnit *ncu = get_enclosing_classbkunit(cu);
    if (ncu != NULL)
    {
        return ncu->enclosing_class_bk;
    }
    return NULL;
}

/**
 * @brief 为实参列表中的各个实参生成加载实参的指令
*/
static void process_arg_list(CompileUnit *cu, Signature *sign)
{
    ASSERT(cu->cur_parser->cur_token.type != TOKEN_RIGHT_PAREN && 
            cu->cur_parser->cur_token.type != TOKEN_RIGHT_BRACKET, "empty argument list!");
    do {
        if (++ sign->arg_num > MAX_ARG_NUM)
        {
            COMPILE_ERROR(cu->cur_parser, "the max number of argument is %d!", MAX_ARG_NUM);
        }
    } while (match_token(cu->cur_parser, TOKEN_COMMA));
}

/**
 * @brief 声明形参列表中的各个形参
*/
static void process_paralist(CompileUnit *cu, Signature *sign)
{
    ASSERT(cu->cur_parser->cur_token.type != TOKEN_RIGHT_PAREN && 
            cu->cur_parser->cur_token.type != TOKEN_RIGHT_BRACKET, "empty argument list!");
    do {
        if (++ sign->arg_num > MAX_ARG_NUM) 
        {
            consume_cur_token(cu->cur_parser, TOKEN_ID, "expect variable name!");
            declare_variable(cu, cu->cur_parser->pre_token.start, cu->cur_parser->pre_token.length);
        }
    } while (match_token(cu->cur_parser, TOKEN_COMMA));
}

/**
 * @brief 尝试编译setter
*/
static bool try_setter(CompileUnit *cu, Signature *sign)
{
    // 进入本函数时候pre_token是方法名
    if (!match_token(cu->cur_parser, TOKEN_ASSIGN))
    {
        return false;
    }

    if (sign->type == SIGN_SUBSCRIPT)
    {
        sign->type = SIGN_SUBSCRIPT_SETTER;
    }
    else
    {
        sign->type = SIGN_SETTER;
    }
    // 读取等号右边的形参左边的(
    consume_cur_token(cu->cur_parser, TOKEN_LEFT_PAREN, "expect '(' after '='!");
    // 读取形参
    consume_cur_token(cu->cur_parser, TOKEN_ID, "expect ID!");
    // 声明形参
    declare_variable(cu, cu->cur_parser->pre_token.start, cu->cur_parser->pre_token.length);

    consume_cur_token(cu->cur_parser, TOKEN_RIGHT_PAREN, "expect ')' after argument list!");
    sign->arg_num ++;
    return true;
}

/**
 * @brief 标识符的签名函数
*/
static void id_method_signature(CompileUnit *cu, Signature *sign)
{
    sign->type = SIGN_GETTER; // 刚识别到id，默认为getter

    // new方法为构造函数
    if (sign->length == 3 && memcmp(sign->name, "new", 3) == 0)
    {
        if (match_token(cu->cur_parser, TOKEN_ASSIGN))
        {
            COMPILE_ERROR(cu->cur_parser, "constructor shouldn't be setter!");
        }
        // 构造函数必须是标准的 即new(_,...)
        if (!match_token(cu->cur_parser, TOKEN_LEFT_PAREN))
        {
            COMPILE_ERROR(cu->cur_parser, "construtor must be method!");
        }

        sign->type = SIGN_CONSTRUCT;
        if (match_token(cu->cur_parser, TOKEN_RIGHT_PAREN))
        {
            return ;
        }
    }
    else
    {
        if (try_setter(cu, sign))
        {
            return ;
        }
        if (!match_token(cu->cur_parser, TOKEN_LEFT_PAREN))
        {
            return ;
        }

        // 值此一般形式的SIGN_METHOD，形式为name(paralist)
        sign->type = SIGN_METHOD;
        if (match_token(cu->cur_parser, TOKEN_LEFT_PAREN))
        {
            return ;
        }
    }

    // 下面处理形参

    process_arg_list(cu, sign);
    consume_cur_token(cu->cur_parser, TOKEN_RIGHT_PAREN, "expect ')' after argument list!");
}

/**
 * @brief 查找局部变量
*/
static int find_local(CompileUnit *cu, const char *name, uint32_t length)
{
    int index = cu->local_var_num - 1;
    while (index >= 0)
    {
        if (cu->local_vars[index].length == length && memcmp(cu->local_vars[index].name, name, length) == 0)
        {
            return index;
        }
        index --;
    }
    return -1;
}

/**
 * @brief 添加upvalue到cu中
*/
static int add_upvalue(CompileUnit *cu, bool is_enclosing_local_var, uint32_t index)
{
    uint32_t idx = 0;
    while (idx < cu->fn->upvalue_num)
    {
        if (cu->upvalues[idx].index == index && cu->upvalues[idx].is_enclosing_local_var == is_enclosing_local_var)
        {
            return idx;
        }
        idx ++;
    }

    cu->upvalues[cu->fn->upvalue_num].is_enclosing_local_var = is_enclosing_local_var;
    cu->upvalues[cu->fn->upvalue_num].index = index;
    return cu->fn->upvalue_num ++;
}

/**
 * @brief 查找name指代的upvalue后添加到cu->upvalue，返回其索引，否则返回-1
*/
static int find_upvalue(CompileUnit *cu, const char *name, uint32_t length)
{   
    if (cu->enclosing_unit == NULL)
    {
        return -1;
    }
    if (!strchr(name, ' ') && cu->enclosing_unit->enclosing_class_bk != NULL)
    {
        return -1;
    }

    int direct_outer_local_index = find_local(cu->enclosing_unit, name, length);

    if (direct_outer_local_index != -1)
    {
        cu->enclosing_unit->local_vars[direct_outer_local_index].is_upvalue = true;
        return add_upvalue(cu, true, (uint32_t)direct_outer_local_index);
    }

    // 向外层查找
    int direct_outer_upvalue_index = find_upvalue(cu->enclosing_unit, name, length);
    if (direct_outer_upvalue_index != -1)
    {
        return add_upvalue(cu, false, (uint32_t)direct_outer_upvalue_index);
    }

    return -1;
}

/**
 * @brief 从局部变量和upvalue查找符号name
*/
static Variable get_var_from_local_or_upvalue(CompileUnit *cu, const char* name, uint32_t length)
{
    Variable var;
    var.scope_type = VAR_SCOPE_INVALID;

    var.index = find_local(cu, name, length);
    if (var.index != -1)
    {
        var.scope_type = VAR_SCOPE_LOCAL;
        return var;
    }

    var.index = find_upvalue(cu, name, length);
    if (var.index != -1)
    {
        var.scope_type = VAR_SCOPE_UPVALUE;
    }
    return var;
}

/**
 * @brief 生成把变量var加载到栈的指令
*/
static void emit_load_variable(CompileUnit *cu, Variable var)
{
    switch (var.scope_type)
    {
        case VAR_SCOPE_LOCAL:
            write_opcode_byte_operand(cu, OPCODE_LOAD_LOCAL_VAR, var.index);
            break;
        case VAR_SCOPE_UPVALUE:
            write_opcode_byte_operand(cu, OPCODE_LOAD_UPVALUE, var.index);
            break;
        case VAR_SCOPE_MODULE:
            write_opcode_short_operand(cu, OPCODE_LOAD_MODULE_VAR, var.index);
            break;
        default:
            NOT_REACHED();
    }
}

/**
 * @brief 为变量var生成存储的指令
*/
static void emit_store_variable(CompileUnit *cu, Variable var)
{
    switch (var.scope_type)
    {
        case VAR_SCOPE_LOCAL:
            write_opcode_byte_operand(cu, OPCODE_STORE_LOCAL_VAR, var.index);
            break;
        case VAR_SCOPE_UPVALUE:
            write_opcode_byte_operand(cu, OPCODE_STORE_UPVALUE, var.index);
            break;
        case VAR_SCOPE_MODULE:
            write_opcode_short_operand(cu, OPCODE_STORE_MODULE_VAR, var.index);
            break;
        default:
            NOT_REACHED();
    }
}

/**
 * @brief 生成加载或存储的指令
*/
static void emit_load_or_store_variable(CompileUnit *cu, bool can_assign, Variable var)
{
    if (can_assign && match_token(cu->cur_parser, TOKEN_ASSIGN))
    {
        expression(cu, BP_LOWEST); // 计算=右边的表达式的值
        emit_store_variable(cu, var);
    }
    else 
    {
        emit_load_variable(cu, var);
    }
}

/**
 * @brief 生成把实例对象this加载到栈的指令
*/
static void emit_load_this(CompileUnit *cu)
{
    Variable var = get_var_from_local_or_upvalue(cu, "this", 4);
    ASSERT(var.scope_type != VAR_SCOPE_INVALID, "get variable failed!");
    emit_load_variable(cu, var);
}

/**
 * @brief 编译代码块
*/
static void compile_block(CompileUnit *cu)
{
    // 进入本函数之前已经读入了{
        while (!match_token(cu->cur_parser, TOKEN_RIGHT_BRACE))
        {
            if (PEEK_TOKEN(cu->cur_parser) == TOKEN_EOF)
            {
                COMPILE_ERROR(cu->cur_parser, "expect ')' at the end of block!");
            }
            compile_program(cu);
        }
}

/**
 * @brief 编译函数或方法体
*/
static void compile_body(CompileUnit *cu, bool is_construct)
{
    // 进入本函数之前已经读入了{
    compile_block(cu);

    if (is_construct)
    {
        write_opcode_byte_operand(cu, OPCODE_STORE_LOCAL_VAR, 0);
    }
    else
    {
        // 否则加载null占位
        write_opcode(cu, OPCODE_PUSH_NULL);
    }
    // 构造函数返回this，否则返回null
    write_opcode(cu, OPCODE_RETURN);
}

#if DEBUG
static ObjFn* end_compile_unit(CompileUnit *cu, const char *debug_name, uint32_t debug_name_len)
{
    bind_debug_fn_name(cu->cur_parser->vm, cu->fn->debug, debug_name, debug_name_len);
}
#else
static ObjFn* end_compile_unit(CompileUnit *cu) {
#endif
    write_opcode(cu, OPCODE_END); // 标识单元编译结束
    if (cu->enclosing_unit != NULL)
    {
        // 把当前编译的objfn作为常量添加到父编译单元的常量表
        uint32_t index = add_constant(cu->enclosing_unit, OBJ_TO_VALUE(cu->fn));

        // 内层函数以闭包形式在外层函数中村中
        // 在外层函数的指令流中添加“为当前内层函数创建闭包的指令”
        write_opcode_short_operand(cu->enclosing_unit, OPCODE_CREATE_CLASS, index);

        // 为vm在创建闭包时判断引用的是局部变量还是upvalue
        // 下面为每个upvalue生成参数
        index = 0;
        while (index < cu->fn->upvalue_num)
        {
            write_byte(cu->enclosing_unit, cu->upvalues[index].is_enclosing_local_var ? 1 : 0);
            write_byte(cu->enclosing_unit, cu->upvalues[index].index);
            index ++;
        }
    }
    // 下调本编译单元，使当前编译单元指向外层编译单元
    cu->cur_parser->cur_compileUnit = cu->enclosing_unit;
    return cu->fn; // 编译单元被编译的结果就是一个objfn
}

/**
 * @brief 生成getter或一般method调用指令
*/
static void emit_getter_method_call(CompileUnit *cu, Signature *sign, OpCode opcode)
{
    Signature new_sign;
    new_sign.type = SIGN_GETTER;
    new_sign.name = sign->name;
    new_sign.length = sign->length;
    new_sign.arg_num = 0;

    // 如果是method。在生成调用方法的指令前必须把参数入栈
    if (match_token(cu->cur_parser, TOKEN_LEFT_PAREN))
    {
        new_sign.type = SIGN_METHOD;

        if (!match_token(cu->cur_parser, TOKEN_RIGHT_PAREN)) // 有参数
        {
            process_arg_list(cu, &new_sign);
            consume_cur_token(cu->cur_parser, TOKEN_RIGHT_PAREN, "expect ')' after argument list!");
        }
    }
    if (match_token(cu->cur_parser, TOKEN_LEFT_BRACE)) // 块参数
    {
        new_sign.arg_num ++;
        new_sign.type = SIGN_METHOD;
        CompileUnit fn_cu;
        init_compileUnit(cu->cur_parser, &fn_cu, cu, false);

        Signature tmp_fn_sign = { SIGN_METHOD, "", 0, 0 };
        if (match_token(cu->cur_parser, TOKEN_BIT_OR)) // 块参数的参数
        {
            process_paralist(&fn_cu, &tmp_fn_sign);
            consume_cur_token(cu->cur_parser, TOKEN_BIT_OR, "expect '|' after argument list!");
        }
        fn_cu.fn->arg_num = tmp_fn_sign.arg_num;

        // 编译函数体
        compile_body(&fn_cu, false);
#if DEBUG   
        char fn_name[MAX_SIGN_LEN + 10] = { '\0' };
        uint32_t len = sign_to_string(&new_sign, fn_name);
        memmove(fn_name + len, " block arg", 10);
        end_compile_unit(&fn_cu, fn_name, len + 10);
#else
        end_compile_unit(&fn_cu);
#endif
    }
    // 如果是在构造函数中调用了super则会执行到此，构造函数中调用的方法只能是super
    if (sign->type == SIGN_CONSTRUCT)
    {
        if (new_sign.type != SIGN_METHOD)
        {
            COMPILE_ERROR(cu->cur_parser, "the form of supercall is super() pr super(argument)");
        }
        new_sign.type = SIGN_CONSTRUCT;
    }

    // 根据签名生成调用指令
    emit_call_by_signature(cu, &new_sign, opcode);
}

/**
 * @brief 生成方法调用指令，包括getter和setter
*/
static void emit_method_call(CompileUnit *cu, const char *name, uint32_t length, OpCode opcode, bool can_assign)
{
    Signature sign;
    sign.type = SIGN_GETTER;
    sign.name = name;
    sign.length = length;

    // 若是setter则生成调用setter的指令
    if (match_token(cu->cur_parser, TOKEN_ASSIGN) && can_assign)
    {
        sign.type = SIGN_SETTER;
        sign.arg_num = 1; // 只接受一个参数
        expression(cu, BP_LOWEST); // 载入实参(即=右边所赋的值)
        emit_call_by_signature(cu, &sign, opcode);
    }
    else
    {
        emit_getter_method_call(cu, &sign, opcode);
    }
}

/**
 * @brief 小写字符开头便是局部变量
*/
static bool is_local_name(const char *name)
{   
    return (name[0] >= 'a' && name[0] <= 'z');
}

/**
 * @brief 标识符.nud()：变量名或方法名
*/
static void id(CompileUnit *cu, bool can_assign)
{
    Token name = cu->cur_parser->pre_token;
    ClassBookKeep *class_bk = get_enclosing_classbk(cu);

    // 顺序
    // 函数-》局部变量和upvalue-》实例域-》静态域-》类getter方法调用-》模块变量
    if (cu->enclosing_unit == NULL && match_token(cu->cur_parser, TOKEN_LEFT_PAREN))
    {
        // 函数名加上Fn 前缀作为模块变量名
        char id[MAX_ID_LEN] = { '\0' };
        memmove(id, "Fn ", 3);
        memmove(id + 3, name.start, name.length);

        Variable var;
        var.scope_type = VAR_SCOPE_MODULE;
        var.index = get_index_from_symbol_table(&cu->cur_parser->cur_module->module_var_name, id, strlen(id));

        if (var.index == -1)
        {
            memmove(id, name.start, name.length);
            id[name.length] = '\0';
            COMPILE_ERROR(cu->cur_parser, "undefined function: '%s'!", id);
        }
        // 把模块变量即函数闭包加载到栈
        emit_load_variable(cu, var);

        Signature sign;
        sign.type = SIGN_METHOD;
        sign.name = "call";
        sign.length = 4;
        sign.arg_num = 0;

        if (!match_token(cu->cur_parser, TOKEN_RIGHT_PAREN))
        {
            // 压入实参
            process_arg_list(cu, &sign);
            consume_cur_token(cu->cur_parser, TOKEN_RIGHT_PAREN, "expect ')' after argument list!");
        }

        // 生成调用指令以调用函数
        emit_call_by_signature(cu, &sign, OPCODE_CALL0);
    }
    else
    {
        Variable var = get_var_from_local_or_upvalue(cu, name.start, name.length);
        if (var.index != -1)
        {
            emit_load_or_store_variable(cu, can_assign, var);
            return ; 
        }
        if (class_bk != NULL)
        {
            int field_index = get_index_from_symbol_table(&class_bk->fields, name.start, name.length);
            if (field_index != -1)
            {
                bool is_read = true;
                if (can_assign && match_token(cu->cur_parser, TOKEN_ASSIGN))
                {
                    is_read = false;
                    expression(cu, BP_LOWEST);
                }
                // 如果当前正在编译类方法，则直接在该实例对象中加载filed
                if (cu->enclosing_unit != NULL)
                {
                    write_opcode_byte_operand(cu, is_read ? OPCODE_LOAD_THIS_FILED: OPCODE_STORE_THIS_FIELD, field_index);
                }
                else
                {
                    emit_load_this(cu);
                    write_opcode_byte_operand(cu, is_read ? OPCODE_LOAD_THIS_FILED: OPCODE_STORE_THIS_FIELD, field_index);
                }
                return ;
            }
        }
        // 按照静态域查找
        if (class_bk != NULL)
        {
            char *static_field_id = ALLOCATE_ARRAY(cu->cur_parser->vm, char, MAX_ID_LEN);
            memset(static_field_id, 0, MAX_ID_LEN);
            uint32_t static_field_id_len;
            char cls_name = class_bk->name->value.start;
            uint32_t cls_len = class_bk->name->value.length;

            memmove(static_field_id, "Cls", 3);
            memmove(static_field_id + 3, cls_name, cls_len);
            memmove(static_field_id + 3 + cls_len, " ", 1);
            const char tk_name = name.start;
            uint32_t tk_len = name.length;
            memmove(static_field_id + 4 + cls_len, tk_name, tk_len);
            static_field_id_len = strlen(static_field_id);
            var = get_var_from_local_or_upvalue(cu, static_field_id, static_field_id_len);
            DEALLOCATE_ARRAY(cu->cur_parser->vm, static_field_id, MAX_ID_LEN);
            if (var.index != -1)
            {
                emit_load_or_store_variable(cu, can_assign, var);
                return ;
            }
        }
        // 该标识符是同类中的其他方法调用
        if (class_bk != NULL && is_local_name(name.start))
        {
            emit_load_this(cu); // 确保args[0]是this对象

            emit_method_call(cu, name.start, name.length, OPCODE_CALL0, can_assign);
            return ;
        }
        // 按照模块变量处理
        var.scope_type = VAR_SCOPE_MODULE;
        var.index = get_index_from_symbol_table(&cu->cur_parser->cur_module->module_var_name, name.start, name.length);

        if (var.index == -1)
        {
            // 模块变量属于模块作用域，若当前引用处之前未定义该模块变量
            // 说不定在后面有其定义，因此暂时先声明

            char fn_name[MAX_SIGN_LEN + 4] = { '\0' };
            memmove(fn_name, "Fn ", 3);
            memmove(fn_name + 3, name.start, name.length);
            var.index = get_index_from_symbol_table(&cu->cur_parser->cur_module->module_var_name, fn_name, strlen(fn_name));

            // 若不是函数名，那可能是该模块变量定义在引用处的后面
            // 先将行号作为该变量去声明
            if (var.index == -1)
            {
                var.index = declare_module_var(cu->cur_parser->vm, cu->cur_parser->cur_module, 
                                                name.start, name.length, NUM_TO_VALUE(cu->cur_parser->cur_token.lineNo));
            }
        }
        emit_load_or_store_variable(cu, can_assign, var);
    }
}

/**
 * @brief 生成加载类的指令
*/
static void emit_load_module_var(CompileUnit *cu, const char *name)
{
    int index = get_index_from_symbol_table(&cu->cur_parser->cur_module->module_var_name, name, strlen(name));

    ASSERT(index != -1, "symbol should have been defined");
    write_opcode_short_operand(cu, OPCODE_LOAD_MODULE_VAR, index);
}

/**
 * @brief 内嵌表达式
*/
static void string_interpolation(CompileUnit *cu, bool can_assign UNUSED)
{
    /**
     * a%(b+c) d%(e) f
     * 会按照如下形式编译
     * ["a", b+c, "d",e,"f"].join()
     * a和d是TOKEN_INTERPOLATION bcd都是TOKEN)ID f是TOKEN_STRING
    */
   emit_load_module_var(cu, "List");
   emit_call(cu, 0, "new()", 5);

   // 每次处理字符串中的一个内嵌表达式
   do {
        literal(cu, false); // 
        emit_call(cu, 1, "addCore_(_)", 11);
        expression(cu, BP_LOWEST);
        emit_call(cu, 1, "addCore_(_)", 11);
   } while (match_token(cu->cur_parser, TOKEN_INTERPOLATION));

   consume_cur_token(cu->cur_parser, TOKEN_STRING, "expect string at the end of interpolatation");

   literal(cu, false);

   emit_call(cu, 1, "addCore_(_)", 11);

   emit_call(cu, 0, "join()", 6);
}

/**
 * @brief 编译bool
*/
static void boolean(CompileUnit *cu, bool can_assign UNUSED)
{
    OpCode opcode = cu->cur_parser->pre_token.type == TOKEN_TRUE ? OPCODE_PUSH_TRUE: OPCODE_PUSH_FALSE;
    write_opcode(cu, opcode);
}

/**
 * @brief 生成OPCODE_PUSH_NULL指令
*/
static void null(CompileUnit *cu, bool can_assign UNUSED)
{
    write_opcode(cu, OPCODE_PUSH_NULL);
}

/**
 * @brief "this".nud()
*/
static void this(CompileUnit *cu, bool can_assign UNUSED)
{
    if (get_enclosing_classbk(cu) == NULL)
    {
        COMPILE_ERROR(cu->cur_parser, "this must be inside a class method!");
    }
    emit_load_this(cu);
}

/**
 * @brief “super”.nud()
*/
static void super(CompileUnit *cu, bool can_assign)
{
    ClassBookKeep *enclosing_classbk = get_enclosing_classbk(cu);
    if (enclosing_classbk = NULL)
    {
        COMPILE_ERROR(cu->cur_parser, "can't invoke super outside a class method!");
    }

    emit_load_this(cu); // 此处加载this，确保arg[0]始终是this

    // 判断形式super.methodname()
    if (match_token(cu->cur_parser, TOKEN_DOT))
    {
        consume_cur_token(cu->cur_parser, TOKEN_ID, "expect name after '.'!");
        emit_method_call(cu, cu->cur_parser->pre_token.start, cu->cur_parser->pre_token.length, OPCODE_SUPER0, can_assign);
    }
    else
    {
        // super()调用基类中关键字super所在子类方法同名的方法
        emit_getter_method_call(cu, enclosing_classbk->signature, OPCODE_SUPER0);
    }
}

/**
 * @brief 编译圆括号
*/
static void parenthesis(CompileUnit *cu, bool can_assign UNUSED)
{
    expression(cu, BP_LOWEST);
    consume_cur_token(cu->cur_parser, TOKEN_RIGHT_PAREN, "expect ')' after expression!");
}

/**
 * @brief '['.nud() 
*/
static void list_literal(CompileUnit *cu, bool can_assign UNUSED)
{
    emit_load_module_var(cu, "List");
    emit_call(cu, 0, "new()", 5);

    do {
        if (PEEK_TOKEN(cu->cur_parser) == TOKEN_RIGHT_BRACKET)
        {
            break;
        }
        expression(cu, BP_LOWEST);
        emit_call(cu, 1, "addCore_(_)", 11);
    } while (match_token(cu->cur_parser, TOKEN_COMMA));

    consume_cur_token(cu->cur_parser, TOKEN_RIGHT_BRACKET, "expect ')' after list element!");
}

/**
 * @brief '['.lef() 用于索引
*/
static void subscript(CompileUnit *cu, bool can_assign)
{
    if (match_token(cu->cur_parser, TOKEN_RIGHT_BRACKET))
    {
        COMPILE_ERROR(cu->cur_parser, "need argument in the '[]'!");
    }

    Signature sign = {SIGN_SUBSCRIPT, "", 0, 0};

    // 读取参数并把参数加载到栈，统计参数个数
    process_arg_list(cu, &sign);
    consume_cur_token(cu->cur_parser, TOKEN_RIGHT_BRACKET, "expect ']' after argument list!");

    if (can_assign && match_token(cu->cur_parser, TOKEN_ASSIGN))
    {
        sign.type = SIGN_SUBSCRIPT_SETTER;

        if (++ sign.arg_num > MAX_ARG_NUM)
        {
            COMPILE_ERROR(cu->cur_parser, "the max number of argument is %d!", MAX_ARG_NUM);
        }
        expression(cu, BP_LOWEST); // 获取=右边的表达式
    }
    emit_call_by_signature(cu, &sign, OPCODE_CALL0);
}   

/**
 * @brief 为下标操作符[编译签名
*/
static void subscript_method_signature(CompileUnit *cu, Signature *sign)
{
    sign->type = SIGN_SUBSCRIPT;
    sign->type = 0;
    process_paralist(cu, sign);
    consume_cur_token(cu->cur_parser, TOKEN_RIGHT_BRACKET, "expect ']' after index list!");
    try_setter(cu, sign);  // 判断]后面是否接=为setter
}

static void call_entry(CompileUnit *cu, bool can_assign) 
{
    // 本函数是'.'.led() 当前的token是TOKEN_ID
    consume_cur_token(cu->cur_parser, TOKEN_ID, "expect method name after '.'!");

    emit_method_call(cu, cu->cur_parser->pre_token.start, cu->cur_parser->pre_token.length, OPCODE_CALL0, can_assign);
}

/**
 * @brief map对象字面量
*/
static void map_literal(CompileUnit *cu, bool can_assign UNUSED)
{
    emit_load_module_var(cu, "Map");
    emit_call(cu, 0, "new()", 5);

    do 
    {
        if (PEEK_TOKEN(cu->cur_parser) == TOKEN_RIGHT_BRACE)
        {
            break;
        }

        expression(cu, BP_UNARY);
        // 读入key后面的冒号
        consume_cur_token(cu->cur_parser, TOKEN_COLON, "expect ':' after key!");

        expression(cu, BP_LOWEST);
        emit_call(cu, 2, "addCore_(_,_)", 13);
    } while (match_token(cu->cur_parser, TOKEN_COMMA));

    consume_cur_token(cu->cur_parser, TOKEN_RIGHT_BRACE, "map literal should end with \')\'!");
}

static uint32_t emit_instr_with_place_holder(CompileUnit *cu, OpCode opcode)
{

}


SymbolBindRule Rules[] = 
{
    /* TOKEN_INVALID */         UNUSED_RULE,
    /* TOKEN_NUM */             PREFIX_SYMBOL(literal),
    /* TOKEN_STRING */          PREFIX_SYMBOL(literal),
    /* TOKEN_ID  */             {NULL, BP_NONE, id, NULL, id_method_signature},
    /* TOKEN_INTERPOLATION*/    PREFIX_SYMBOL(string_interpolation),
    /* TOKEN_VAR*/              UNUSED_RULE,
    /* TOKEN_FUN */             UNUSED_RULE,
    /* TOKEN_IF */              UNUSED_RULE,
    /* TOKEN_ELSE */            UNUSED_RULE,
    /* TOKEN_TRUE */            PREFIX_SYMBOL(boolean),
    /* TOKEN_FALSE */           PREFIX_SYMBOL(boolean),
    /* TOKEN_WHILE */           UNUSED_RULE,
    /* TOKEN_FOR */             UNUSED_RULE,
    /* TOKEN_BREAK */           UNUSED_RULE,
    /* TOKEN_CONTINUE */        UNUSED_RULE,
    /* TOKEN_RETURN */          UNUSED_RULE,
    /* TOKEN_NULL */            PREFIX_SYMBOL(null),
    /* TOKEN_CLASS */           UNUSED_RULE,
    /* TOKEN_THIS */            PREFIX_SYMBOL(this),
    /* TOKEN_STATIC */          UNUSED_RULE,
    /* TOKEN_IS */              INFIX_OPERATOR("is", BP_IS),
    /* TOKEN_SUPER */           PREFIX_SYMBOL(super),
    /* TOKEN_IMPORT */          UNUSED_RULE,
    /* TOKEN_COMMA */           UNUSED_RULE,
    /* TOKEN_COMMA */           UNUSED_RULE,
    /* TOKEN_LEFT_PAREN */      PREFIX_SYMBOL(parenthesis),
    /* TOKEN_RIGHT_PAREN */     UNUSED_RULE,
    /* TOKEN_LEFT_BRACKET */    {NULL, BP_CALL, list_literal, subscript, subscript_method_signature},
    /* TOKEN_RIGHT_BRACKET */   UNUSED_RULE,
    /* TOKEN_LEFT_BRACE */      PREFIX_SYMBOL(map_literal),
    /* TOKEN_RIGHT_BRACE  */    UNUSED_RULE,
    /* TOKEN_DOT */             INFIX_SYMBOL(BP_CALL, call_entry),
};
